package br.edu.eseg.ganttapplet;

import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Rectangle2D;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.swing.JApplet;

import netscape.javascript.JSObject;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.data.category.IntervalCategoryDataset;
import org.jfree.data.gantt.Task;
import org.jfree.data.gantt.TaskSeries;
import org.jfree.data.gantt.TaskSeriesCollection;
import org.jfree.data.time.SimpleTimePeriod;

public class GanttApplet extends JApplet implements MouseListener,
		MouseMotionListener {
	private static final long serialVersionUID = 1L;
	private Image dbImage;
	private IntervalCategoryDataset dataset;
	private Graphics dbg;
	private JFreeChart chart;
	private JSObject jso;
	private int mX, mY; // Coordenadas do mouse

	public void init() {

		dataset = createDataset();
		chart = ChartFactory.createGanttChart("Gráfico de Gantt", // chart
				"Tarefas", // domain axis label
				"Data", // range axis label
				dataset, // data
				false, true, true); // include legend
		chart.setTextAntiAlias(true);
//		int w = Integer.parseInt(getParameter("width"));
//		int h = Integer.parseInt(getParameter("heigth"));
		setSize(new Dimension(1000,500));
		addMouseListener(this);
		addMouseMotionListener(this);
	}
	

	public void paint(Graphics g) {
		if (dbImage == null) {
			dbImage = createImage(getBounds().getSize().width, getBounds()
					.getSize().height);
			dbg = dbImage.getGraphics();
		}
		dbg.fillRect(0, 0, this.getSize().width, this.getSize().height);
		dbg.setColor(getForeground());
		chart.draw((Graphics2D) dbg, getBounds());
		setSize(new Dimension(getWidth(), getHeight()));
		g.drawImage(dbImage, 0, 0, this);
	}

	@Override
	public void repaint() {
		paint(getGraphics());
	}

	@Override
	public void update(Graphics g) {
		paint(g);
	}

	public void mouseEntered(MouseEvent e) {
		// Chamado quando o ponteiro entra a area da applet.
		mX = e.getX();
		mY = e.getY();

		repaint();
		e.consume();
	}

	public void mouseExited(MouseEvent e) {
		// Chamado quando o ponteiro sai da area da applet.
	}

	public void mouseClicked(MouseEvent e) {
		// Chamado quando o usuario clica e solta o botao do mouse sem move-lo.
		mX = e.getX();
		mY = e.getY();

		CategoryPlot plot = chart.getCategoryPlot();
		List l = plot.getCategoriesForAxis(plot.getDomainAxis());

		Rectangle2D dataarea = plot.getDataArea();

		double x1 = dataarea.getMinX();
		double x0 = x1 - x1 * .8;

		if (x0 <= mX && mX <= x1) {

			buscaTarefa(l, mY);

		}
		repaint();
		e.consume();
	}

	public void buscaTarefa(List tarefas, int y) {
		int esq = 0;
		int dir = tarefas.size() - 1;
		int meio;

		while (esq <= dir) {
			meio = esq + ((dir - esq) / 2);

			double y0 = chart
					.getCategoryPlot()
					.getDomainAxis()
					.getCategoryStart(meio, tarefas.size(),
							chart.getCategoryPlot().getDataArea(),
							chart.getCategoryPlot().getDomainAxisEdge());
			double y1 = chart
					.getCategoryPlot()
					.getDomainAxis()
					.getCategoryEnd(meio, tarefas.size(),
							chart.getCategoryPlot().getDataArea(),
							chart.getCategoryPlot().getDomainAxisEdge());

			if (y < y0) {
				dir = meio - 1;
			} else if (y > y1) {
				esq = meio + 1;
			} else {
				Comparable t = (Comparable) tarefas.get(meio);
				try {
					jso = JSObject.getWindow(this);
					jso.call("alert", new Object[] { "Voce clicou na tarefa: "
							+ t });
					getAppletContext().showDocument(
							new URL(
									"javascript:doAlert(\"oce clicou na tarefa: "
											+ t + "\")"));
				} catch (MalformedURLException e) {
					e.printStackTrace();
				}
				System.out.println(t + " y0=" + y0 + " y1=" + y1);
				break;
			}
		}
	}

	public void mousePressed(MouseEvent e) {
		// Chamado quando um botao eh pressionado

	}

	public void mouseReleased(MouseEvent e) {
		// Chamado depois que um botao eh solto
		repaint();
		e.consume();
	}

	public void mouseMoved(MouseEvent e) {
		// Chamado durante o movimento do mouse sem botoes pressionados
		mX = e.getX();
		mY = e.getY();
		CategoryPlot plot = chart.getCategoryPlot();
		List l = plot.getCategoriesForAxis(plot.getDomainAxis());

		Rectangle2D dataarea = plot.getDataArea();

		double x1 = dataarea.getMinX();
		double x0 = x1 - x1 * .8;
		double y0 = chart
				.getCategoryPlot()
				.getDomainAxis()
				.getCategoryStart(0, l.size(),
						chart.getCategoryPlot().getDataArea(),
						chart.getCategoryPlot().getDomainAxisEdge());
		double y1 = chart
				.getCategoryPlot()
				.getDomainAxis()
				.getCategoryStart(l.size() - 1, l.size(),
						chart.getCategoryPlot().getDataArea(),
						chart.getCategoryPlot().getDomainAxisEdge());

		if (x0 <= mX && mX <= x1 && y0 <= mY && mY <= y1) {
			setCursor(new Cursor(Cursor.HAND_CURSOR));
		} else {
			setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
		}
		showStatus("X=" + mX + " Y=" + mY);
		repaint();
		e.consume();
	}

	public void mouseDragged(MouseEvent e) {
		// Chamado quando o mouse eh movido com botoes pressionados

		repaint();
		e.consume();
	}

	public IntervalCategoryDataset createDataset() {

		final TaskSeries s1 = new TaskSeries("Planejamento");

		Task t0 = new Task("de", new SimpleTimePeriod(date(1,
				Calendar.NOVEMBER, 2001), date(15, Calendar.NOVEMBER, 2001)));

		Task t1 = new Task("Write Proposal", new Date(), new Date());

		Task t2 = new Task("Obtain Approval", new SimpleTimePeriod(date(9,
				Calendar.APRIL, 2001), date(20, Calendar.APRIL, 2001)));
		t2.setPercentComplete(0.5d);

		Task t3 = new Task("Requirements Analysis", new SimpleTimePeriod(date(
				25, Calendar.APRIL, 2001), date(5, Calendar.MAY, 2001)));
		t3.setPercentComplete(0.5);

		Task t4 = new Task("Design Phase", new SimpleTimePeriod(date(6,
				Calendar.MAY, 2001), date(30, Calendar.MAY, 2001)));

		t1.addSubtask(t2);
		t1.addSubtask(t3);
		t1.addSubtask(t4);

		t3.addSubtask(t4);

		t3.addPredecessor(t2);

		s1.add(t0);
		s1.add(t1);
		s1.add(t2);
		s1.add(t3);
		s1.add(t4);

		// t4.addPredecessor(t1);

		t0.addPredecessor(t4);

		Task t5 = new Task("Design Signoff", new SimpleTimePeriod(date(2,
				Calendar.JUNE, 2001), date(2, Calendar.JUNE, 2001)));
		t5.setMilestone(true);
		s1.add(t5);
		s1.add(new Task("Alpha Implementation", new SimpleTimePeriod(date(3,
				Calendar.JUNE, 2001), date(31, Calendar.JULY, 2001))));
		Task t7 = new Task("Design Review", new SimpleTimePeriod(date(1,
				Calendar.AUGUST, 2001), date(8, Calendar.AUGUST, 2001)));

		t7.addRecurso("Robson");
		t7.addRecurso("Renan");
		s1.add(t7);

		Task t8 = new Task("Revised Design Signoff", new SimpleTimePeriod(date(
				10, Calendar.AUGUST, 2001), date(10, Calendar.AUGUST, 2001)));
		t8.addPredecessor(t7);
		t8.setMilestone(true);
		s1.add(t8);
		s1.add(new Task("Beta Implementation", new SimpleTimePeriod(date(12,
				Calendar.AUGUST, 2001), date(12, Calendar.SEPTEMBER, 2001))));
		
		Task t12 =new Task("Testing", new SimpleTimePeriod(date(13,
				Calendar.SEPTEMBER, 2001), date(31, Calendar.OCTOBER, 2001))); 
		t12.addRecurso("rogerio");
		s1.add(t12);
		
		Task t13 =new Task("Final Implementation", new SimpleTimePeriod(date(1,
				Calendar.NOVEMBER, 2001), date(15, Calendar.NOVEMBER, 2001))); 
		t13.addRecurso("Fernanda");
		s1.add(t13);

		s1.add(new Task("Signoff14", new SimpleTimePeriod(date(28,
				Calendar.NOVEMBER, 2001), date(30, Calendar.NOVEMBER, 2001))));

		
		Task t15 = new Task("Signoff15", new SimpleTimePeriod(date(28,
				Calendar.NOVEMBER, 2001), date(30, Calendar.NOVEMBER, 2001))); 
		t15.addRecurso("Fulano1");
		s1.add(t15);

		
		
		Task t16 = new Task("Signoff16", new SimpleTimePeriod(date(28,
				Calendar.NOVEMBER, 2001), date(30, Calendar.NOVEMBER, 2001)));
		t16.addRecurso("Fulano1");
		t16.addRecurso("Fulano2");
		s1.add(t16);
		
		Task t17 = new Task("Signoff17", new SimpleTimePeriod(date(28,
				Calendar.NOVEMBER, 2001), date(30, Calendar.NOVEMBER, 2001)));
		t17.addRecurso("Fulano1");
		t17.addRecurso("Fulano2");
		t17.addRecurso("Fulano3");
		s1.add(t17);
		Task tf = new Task("Signoff18", new SimpleTimePeriod(date(28,
				Calendar.NOVEMBER, 2001), date(30, Calendar.NOVEMBER, 2001)));
		tf.addRecurso("Fulano1");
		tf.addRecurso("Fulano2");
		tf.addRecurso("Fulano3");
		tf.addRecurso("Fulano4");
		s1.add(tf);

		final TaskSeriesCollection collection = new TaskSeriesCollection();
		collection.add(s1);

		return collection;
	}

	private static Date date(final int day, final int month, final int year) {

		final Calendar calendar = Calendar.getInstance();
		calendar.set(year, month, day);
		final Date result = calendar.getTime();
		return result;

	}
}